package com.sweet.jpa.repository;

import com.sweet.page.Page;
import com.sweet.page.Pageable;
import org.springframework.data.repository.NoRepositoryBean;

import java.util.List;

/**
 * 自定义语言操作的持久层
 *
 * @param <T> 实体
 */
@NoRepositoryBean
public interface CustomRepository<T> {
    /**
     * 查询语言
     */
    enum QueryLanguage {
        //HQL,     //Hibernate Query Language，Hibernate执行语言，本持久层不支持
        JPQL,      //JPA Query Language，JAP执行语言,和HQL使用?定义参数和设值不一样
        NATIVE     //Native Query Language，本地数据库语言
    }

    /**
     * 执行更新
     * 使用占位符设值
     *
     * @param language    语句类型
     * @param queryString 操作语句
     * @param values      占位符值列表，从?0开始
     * @return
     */
    int executeUpdate(QueryLanguage language, String queryString, Object... values);

    /**
     * 获取总数
     * 使用占位符设值
     *
     * @param language    语句类型
     * @param queryString 操作语句
     * @param values      占位符值列表，从?0开始
     * @return int
     * 若为聚合函数，使用jpql/hql返回的为java.util.Long，则可以直接(Long)result返回
     * 若为聚合函数，使用sql返回的为java.math.BigInteger，需要使用BigInteger.longValue()来获得
     */
    int getCount(QueryLanguage language, String queryString, Object... values);

    /**
     * 查询实体列表
     * 使用占位符设值
     *
     * @param language    语句类型
     * @param queryString 操作语句
     * @param values      占位符值列表，从?0开始
     * @return
     */
    List<T> getAll(QueryLanguage language, String queryString, Object... values);

    /**
     * 查询部分属性列表
     * 使用占位符设值
     *
     * @param language    语句类型
     * @param queryString 操作语句,若为HQL语句，当未指定查询的列时，Object[]为Entity实体对象
     * @param values      占位符值列表，从?0开始
     * @return
     */
    List<Object[]> getArray(QueryLanguage language, String queryString, Object... values);

    /**
     * 查询转为其他实体列表
     * 使用占位符设值
     *
     * @param language    语句类型
     * @param queryString 操作语句,若为HQL语句，当未指定查询的列时，Object[]为Entity实体对象
     * @param values      占位符值列表，从?0开始
     * @return List<O>
     */
    <O> List<O> getObject(QueryLanguage language, String queryString, Object... values);

    /**
     * 分页查询
     * 使用占位符设值
     *
     * @param pageable    分页参数
     * @param language    语句类型
     * @param queryString 操作语句
     * @param values      占位符值列表，从?0开始
     * @return
     */
    Page<T> getAll(Pageable pageable, QueryLanguage language, String queryString, Object... values);

    /**
     * 查询部分属性分页
     * 使用占位符设值
     *
     * @param pageable    分页参数
     * @param language    语句类型
     * @param queryString 操作语句,若为HQL语句，当未指定查询的列时，Object[]为Entity实体对象
     * @param values      占位符值列表，从?0开始
     * @return
     */
    Page<Object[]> getArray(Pageable pageable, QueryLanguage language, String queryString, Object... values);

    /**
     * 查询转为其他实体分页
     * 使用占位符设值
     *
     * @param pageable    分页参数
     * @param language    语句类型
     * @param queryString 操作语句
     * @param values      占位符值列表，从?0开始
     * @return List<O>
     */
    <O> Page<O> getObject(Pageable pageable, QueryLanguage language, String queryString, Object... values);

    /**
     * 查询唯一结果
     * 使用占位符设值
     *
     * @param language    语句类型
     * @param queryString 操作语句
     * @param values      占位符值列表，从?0开始
     * @return Object
     */
    Object getUniqueResult(QueryLanguage language, String queryString, Object... values);
}